﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;


public class FM_KeySignature : FM_BaseNote
{
    private readonly FM_KeySignatureValue value;
    private FM_ClefValue clef;

    private List<float> displacement = new List<float>();
    private List<int> accidental = new List<int>();

    public FM_KeySignature(FM_ClefValue clef, FM_KeySignatureValue key, FM_ScoreBase score) : base(FM_NoteType.KEY_SIGNATURE, score)
    {
        this.value = key;
        this.clef = clef;
        Build();
    }

    private void Build()
    {
        accidental.Clear();
        displacement.Clear();
        int cntSharp = 0;
        int cntFlat = 0;

        if (value == FM_KeySignatureValue.DO || value == FM_KeySignatureValue.LAm) return;
        if (value == FM_KeySignatureValue.SOL || value == FM_KeySignatureValue.MIm) cntSharp = 1;
        if (value == FM_KeySignatureValue.RE || value == FM_KeySignatureValue.SIm) cntSharp = 2;
        if (value == FM_KeySignatureValue.LA || value == FM_KeySignatureValue.FAsharpm) cntSharp = 3;
        if (value == FM_KeySignatureValue.MI || value == FM_KeySignatureValue.DOsharpm) cntSharp = 4;
        if (value == FM_KeySignatureValue.SI || value == FM_KeySignatureValue.SOLsharpm) cntSharp = 5;
        if (value == FM_KeySignatureValue.FAsharp || value == FM_KeySignatureValue.REsharpm) cntSharp = 6;
        if (value == FM_KeySignatureValue.DOsharp || value == FM_KeySignatureValue.LAsharpm) cntSharp = 7;

        if (value == FM_KeySignatureValue.FA || value == FM_KeySignatureValue.REm) cntFlat = 1;
        if (value == FM_KeySignatureValue.SIb || value == FM_KeySignatureValue.SOLm) cntFlat = 2;
        if (value == FM_KeySignatureValue.MIb || value == FM_KeySignatureValue.DOm) cntFlat = 3;
        if (value == FM_KeySignatureValue.LAb || value == FM_KeySignatureValue.FAm) cntFlat = 4;
        if (value == FM_KeySignatureValue.REb || value == FM_KeySignatureValue.SIbm) cntFlat = 5;
        if (value == FM_KeySignatureValue.SOLb || value == FM_KeySignatureValue.MIbm) cntFlat = 6;
        if (value == FM_KeySignatureValue.DOb || value == FM_KeySignatureValue.LAbm) cntFlat = 7;

        for (int i = 0; i < cntSharp; i++) accidental.Add((int)FM_Accidental.Sharp);
        for (int i = 0; i < cntFlat; i++) accidental.Add((int)FM_Accidental.Flat);

        if (cntSharp >= cntFlat)
        {
            if (clef == FM_ClefValue.TREBLE)
            {
                displacement.Add(0.0f);
                displacement.Add(1.5f);
                displacement.Add(-0.5f);
                displacement.Add(1.0f);
                displacement.Add(2.5f);
                displacement.Add(0.5f);
                displacement.Add(2.0f);
            }
            if (clef == FM_ClefValue.BASS)
            {
                displacement.Add(1 + 0.0f);
                displacement.Add(1 + 1.5f);
                displacement.Add(1 - 0.5f);
                displacement.Add(1 + 1.0f);
                displacement.Add(1 + 2.5f);
                displacement.Add(1 + 0.5f);
                displacement.Add(1 + 2.0f);
            }
        }
        else
        {
            if (clef == FM_ClefValue.TREBLE)
            {
                displacement.Add(2.0f);
                displacement.Add(0.5f);
                displacement.Add(2.5f);
                displacement.Add(1.0f);
                displacement.Add(3.0f);
                displacement.Add(1.5f);
                displacement.Add(3.5f);
            }
            if (clef == FM_ClefValue.BASS)
            {
                displacement.Add(1 + 2.0f);
                displacement.Add(1 + 0.5f);
                displacement.Add(1 + 2.5f);
                displacement.Add(1 + 1.0f);
                displacement.Add(1 + 3.0f);
                displacement.Add(1 + 1.5f);
                displacement.Add(1 + 3.5f);
            }
        }
    }

    public override float GetDisplacement()
    {
        return 0.0f;
    }

    public override string AsString()
    {
        StringBuilder s = new StringBuilder();
        foreach (int acc in accidental)
        {
            if (acc == (int)FM_Accidental.Sharp) s.Append(FM_Const.Sharp);
            if (acc == (int)FM_Accidental.Flat) s.Append(FM_Const.Flat);
        }
        return s.ToString();
    }

    public override float WidthAccidental()
    {
        return 0;
    }

    public override float WidthNoteNoStem()
    {
        if (score.score == null) return 0;
        string s = AsString();
        if (s.Equals("")) return 0;
        FM_Const.AdjustFont(score.score, AsString(), 2);
        return score.score.Font.MeasureText(AsString()) + (accidental.Count - 1) * FM_Const.dpTOpx(2);
    }

    public override float WidthNote()
    {
        return WidthNoDotNoStem();
    }

    public override float WidthDot()
    {
        return 0;
    }

    public void DrawNote(ScoreCanvas canvas, FM_ClefValue clef)
    {
        if (score.score == null) return;
        if (!IsVisible()) return;
        this.clef = clef;
        Build();
        base.DrawNote(canvas);

        float dx = StartX + paddingLeft;
        foreach (int acc in accidental)
        {
            float offset = displacement[accidental.IndexOf(acc)];
            float dy = StartY1 + offset * score.score.GetDistanceBetweenStaveLines();

            FM_Const.AdjustFont(score.score, AsString(), 2);
            if (acc == (int)FM_Accidental.Sharp)
            {
                canvas.DrawText(FM_Const.Sharp, dx, dy, score.score.Font);
                dx = dx + score.score.Font.MeasureText(FM_Const.Sharp) + FM_Const.dpTOpx(2);
            }
            if (acc == (int)FM_Accidental.Flat)
            {
                canvas.DrawText(FM_Const.Flat, dx, dy, score.score.Font);
                dx = dx + score.score.Font.MeasureText(FM_Const.Flat) + FM_Const.dpTOpx(2);
            }
        }
    }

    public override float Left()
    {
        return StartX + paddingLeft;
    }

    public override float Bottom()
    {
        if (score.score == null) return 0;
        float dy;
        float maxDy = -100000;
        foreach (int acc in accidental)
        {
            float offset = displacement[accidental.IndexOf(acc)];
            dy = StartY1 + offset * score.score.GetDistanceBetweenStaveLines();
            if (dy > maxDy) maxDy = dy;
        }
        return maxDy + Height();
    }

    public override float Right()
    {
        return StartX + Width();
    }

    public override float Top()
    {
        if (score.score == null) return 0;
        float minDy = Bottom();
        float dy;
        foreach (int acc in accidental)
        {
            float offset = displacement[accidental.IndexOf(acc)];
            dy = StartY1 + offset * score.score.GetDistanceBetweenStaveLines();
            if (dy < minDy) minDy = dy;
        }
        return minDy - Height();
    }

    private float Height()
    {
        if (score.score == null) return 0;
        FM_Const.AdjustFont(score.score, AsString(), 1);
        Rect bounds = new Rect();
        string s = AsString();
        score.score.Font.GetTextBounds(s, 0, s.Length, bounds);
        return bounds.height;//.Height();
    }
}
